#!/usr/sbin/nft -f

# firewall with standard input rules plus a knock sequence
# for opening port 22

flush ruleset

# Ports for the knock sequence.
# The following lines will be changed by /root/bin/newknockports.sh:
# for that to work keep each define on a separate line.
define P1 = 1
define P2 = 2
define P3 = 3
define P4 = 4
define P5 = 5
define P6 = 6

table inet firewall_table {

    set candidates {
        type ipv4_addr . inet_service
        size 24
        flags dynamic,timeout
    }

    set accepted_clients {
        type ipv4_addr
        size 24
        flags dynamic,timeout
    }

    chain portknock {
        udp dport $P1                                  add @candidates {ip saddr . $P2 timeout 3s}
        udp dport $P2 ip saddr . udp dport @candidates add @candidates {ip saddr . $P3 timeout 3s}
        udp dport $P3 ip saddr . udp dport @candidates add @candidates {ip saddr . $P4 timeout 3s}
        udp dport $P4 ip saddr . udp dport @candidates add @candidates {ip saddr . $P5 timeout 3s}
        udp dport $P5 ip saddr . udp dport @candidates add @candidates {ip saddr . $P6 timeout 3s}
        udp dport $P6 ip saddr . udp dport @candidates add @accepted_clients {ip saddr timeout 3s}
        tcp dport 22 ip saddr @accepted_clients accept
        udp dport {$P1, $P2, $P3, $P4, $P5, $P6} counter drop
    }

    chain input {
        type filter hook input priority 0; policy drop;
        ct state invalid drop
        ct state established,related accept
        iif lo accept
        icmp type {destination-unreachable, echo-request, time-exceeded, parameter-problem} accept
        icmpv6 type {nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert} accept
        udp dport {67, 68, 546, 547} accept
        udp dport 123 accept
        jump portknock
        limit rate 3/minute burst 10 packets log prefix "[NFT] input drop: " counter drop
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

}

